home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / sh.proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  48.9 KB  |  2,054 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/sh.proc.c,v 3.39 1992/11/13 04:19:10 christos Exp $ */
  2. /*
  3.  * sh.proc.c: Job manipulations
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: sh.proc.c,v 3.39 1992/11/13 04:19:10 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "tc.h"
  43. #include "tc.wait.h"
  44.  
  45. #ifdef aiws
  46. # undef HZ
  47. # define HZ 16
  48. #endif /* aiws */
  49.  
  50. #if (defined(_BSD) && defined(_BSD_INCLUDES)) || (defined(IRIS4D) && __STDC__)
  51. # define BSDWAIT
  52. #endif
  53. #ifndef WTERMSIG
  54. # define WTERMSIG(w)    (((union wait *) &(w))->w_termsig)
  55. # ifndef BSDWAIT
  56. #  define BSDWAIT
  57. # endif
  58. #endif /* !WTERMSIG */
  59. #ifndef WEXITSTATUS
  60. # define WEXITSTATUS(w)    (((union wait *) &(w))->w_retcode)
  61. #endif /* !WEXITSTATUS */
  62. #ifndef WSTOPSIG
  63. # define WSTOPSIG(w)    (((union wait *) &(w))->w_stopsig)
  64. #endif /* WSTOPSIG */
  65.  
  66. #ifndef WCOREDUMP
  67. # ifdef BSDWAIT
  68. #  define WCOREDUMP(w)    (((union wait *) &(w))->w_coredump)
  69. # else /* !BSDWAIT */
  70. #  define WCOREDUMP(w)    ((w) & 0200)
  71. # endif /* !BSDWAIT */
  72. #endif /* !WCOREDUMP */
  73.  
  74. /*
  75.  * C Shell - functions that manage processes, handling hanging, termination
  76.  */
  77.  
  78. #define BIGINDEX    9    /* largest desirable job index */
  79.  
  80. #ifdef BSDTIMES
  81. # if defined(SUNOS4) || defined(hp9000)
  82. static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0L, 0L, 0L, 0L,
  83.                 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
  84.  
  85. # else /* !SUNOS4 && !hp9000 */
  86. #  ifdef masscomp
  87. /*
  88.  * Initialization of this structure under RTU 4.1A & RTU 5.0 is problematic
  89.  * because the first two elements are unions of a time_t and a struct timeval.
  90.  * So we'll just have to trust the loader to do the "right thing", DAS DEC-90.
  91.  */
  92. static struct rusage zru;
  93. #  else    /* masscomp */
  94. static struct rusage zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0, 
  95.                 0, 0, 0, 0, 0, 0};
  96. #  endif /* masscomp */
  97. # endif    /* !SUNOS4 && !hp9000 */
  98. #else /* ! BSDTIMES */
  99. # ifdef _SEQUENT_
  100. static struct process_stats zru = {{0L, 0L}, {0L, 0L}, 0, 0, 0, 0, 0, 0, 0,
  101.                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  102. # else /* !_SEQUENT_ */
  103. static struct tms zru = {0L, 0L, 0L, 0L}, lru = {0L, 0L, 0L, 0L};
  104. # endif    /* !_SEQUENT_ */
  105. #endif /* !BSDTIMES */
  106.  
  107. #ifndef RUSAGE_CHILDREN
  108. # define    RUSAGE_CHILDREN    -1
  109. #endif
  110.  
  111. static    void         pflushall    __P((void));
  112. static    void         pflush        __P((struct process *));
  113. static    void         pclrcurr    __P((struct process *));
  114. static    void         padd        __P((struct command *));
  115. static    int         pprint        __P((struct process *, int));
  116. static    void         ptprint    __P((struct process *));
  117. static    void         pads        __P((Char *));
  118. static    void         pkill        __P((Char **, int));
  119. static    struct process    *pgetcurr    __P((struct process *));
  120. static    void         okpcntl    __P((void));
  121.  
  122. /*
  123.  * pchild - called at interrupt level by the SIGCHLD signal
  124.  *    indicating that at least one child has terminated or stopped
  125.  *    thus at least one wait system call will definitely return a
  126.  *    childs status.  Top level routines (like pwait) must be sure
  127.  *    to mask interrupts when playing with the proclist data structures!
  128.  */
  129. sigret_t
  130. /*ARGSUSED*/
  131. pchild(snum)
  132. int snum;
  133. {
  134.     register struct process *pp;
  135.     register struct process *fp;
  136.     register int pid;
  137. #if defined(BSDJOBS) || (!defined(BSDTIMES) && (defined(ODT) || defined(aiws) || defined(uts)))
  138.     extern int insource;
  139. #endif /* BSDJOBS */
  140. #ifdef BSDWAIT
  141.     union wait w;
  142. #else /* !BSDWAIT */
  143.     int     w;
  144. #endif /* !BSDWAIT */
  145.     int     jobflags;
  146. #ifdef BSDTIMES
  147.     struct rusage ru;
  148. #else /* !BSDTIMES */
  149. # ifdef _SEQUENT_
  150.     struct process_stats ru;
  151.     struct process_stats cpst1, cpst2;
  152.     timeval_t tv;
  153. # else /* !_SEQUENT_ */
  154.     struct tms proctimes;
  155.  
  156.     if (!timesdone) {
  157.     timesdone++;
  158.     (void) times(&shtimes);
  159.     }
  160. # endif    /* _SEQUENT_ */
  161. #endif /* BSDTIMES */
  162.  
  163. #ifdef JOBDEBUG
  164.     xprintf("pchild()\n");
  165. #endif    /* JOBDEBUG */
  166.  
  167. /* Christos on where the signal(SIGCHLD, pchild) shoud be:
  168.  *
  169.  * I think that it should go *after* the wait, unlike most signal handlers.
  170.  *
  171.  * In release two (for which I have manuals), it says that wait will remove
  172.  * the first child from the queue of dead children.
  173.  * All the rest of the children that die while in the signal handler of the
  174.  * SIGC(H)LD, will be placed in the queue. If signal is called to re-establish
  175.  * the signal handler, and there are items in the queue, the process will
  176.  * receive another SIGC(H)LD before signal returns. BTW this is from the
  177.  * manual page on comp-sim... Maybe it is not applicable to the hp's, but
  178.  * I read on the news in comp.unix.wizards or comp.unix.questions yesterday
  179.  * that another person was claiming the the signal() call should be after
  180.  * the wait().
  181.  */
  182.  
  183. loop:
  184.     errno = 0;            /* reset, just in case */
  185. #ifdef JOBDEBUG
  186.     xprintf("Waiting...\n");
  187.     flush();
  188. #endif
  189. #ifdef BSDJOBS
  190. # ifdef BSDTIMES
  191.     /* both a wait3 and rusage */
  192. #  if !defined(BSDWAIT) || defined(NeXT) || defined(MACH) || (defined(IRIS4D) && __STDC__ && SYSVREL <= 3)
  193.     pid = wait3(&w,
  194.        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  195. #  else /* BSDWAIT */
  196.     pid = wait3(&w.w_status,
  197.        (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), &ru);
  198. #  endif /* BSDWAIT */
  199. # else /* !BSDTIMES */
  200. #  ifdef _SEQUENT_
  201.     (void) get_process_stats(&tv, PS_SELF, 0, &cpst1);
  202.     pid = waitpid(-1, &w,
  203.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  204.     (void) get_process_stats(&tv, PS_SELF, 0, &cpst2);
  205.     pr_stat_sub(&cpst2, &cpst1, &ru);
  206. #  else    /* !_SEQUENT_ */
  207. #   ifndef POSIX
  208.     /* we have a wait3, but no rusage stuff */
  209.     pid = wait3(&w.w_status,
  210.      (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
  211. #   else /* POSIX */
  212.     pid = waitpid(-1, &w,
  213.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  214. #   endif /* POSIX */
  215. #  endif /* !_SEQUENT_ */
  216. # endif    /* !BSDTIMES */
  217. #else /* !BSDJOBS */
  218. # ifdef BSDTIMES
  219. #  define HAVEwait3
  220.     /* both a wait3 and rusage */
  221. #  ifdef hpux
  222.     pid = wait3(&w.w_status, WNOHANG, 0);
  223. #  else    /* !hpux */
  224.     pid = wait3(&w.w_status, WNOHANG, &ru);
  225. #  endif /* !hpux */
  226. # else /* !BSDTIMES */
  227. # ifdef ODT  /* For Sco Unix 3.2.0 or ODT 1.0 */
  228. #  define HAVEwait3
  229.     pid = waitpid(-1, &w,
  230.         (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG));
  231. # endif /* ODT */        
  232. # if defined(aiws) || defined(uts)
  233. #  define HAVEwait3
  234.     pid = wait3(&w.w_status, 
  235.     (setintr && (intty || insource) ? WNOHANG | WUNTRACED : WNOHANG), 0);
  236. # endif /* aiws || uts */
  237. # ifndef HAVEwait3
  238. #  ifdef UNRELSIGS
  239.     /* no wait3, therefore no rusage */
  240.     /* on Sys V, this may hang.  I hope it's not going to be a problem */
  241. #   ifdef _MINIX
  242.     pid = wait(&w);
  243. #   else /* !_MINIX */
  244.     pid = ourwait(&w.w_status);
  245. #   endif /* _MINIX */
  246. #  else    /* UNRELSIGS */
  247.     /* 
  248.      * XXX: for greater than 3 we should use waitpid(). 
  249.      * but then again, SVR4 falls into the POSIX/BSDJOBS category.
  250.      */
  251.     pid = wait(&w.w_status);
  252. #  endif /* SYSVREL >= 3 */
  253. # endif /* HAVEwait3 */
  254. # endif    /* BSDTIMES */
  255. # ifndef BSDSIGS
  256.     (void) sigset(SIGCHLD, pchild);
  257. # endif /* !BSDSIGS */
  258. #endif /* BSDJOBS */
  259.  
  260. #ifdef JOBDEBUG
  261.     {
  262.     char    buffer[100];
  263.     xsprintf(buffer, "pid %d, retval %x termsig %x retcode %x\n",
  264.          pid, w, WTERMSIG(w), WEXITSTATUS(w));
  265.     xprintf(buffer);
  266.     flush();
  267.     }
  268. #endif /* JOBDEBUG */
  269.  
  270.     if (pid <= 0) {
  271. #ifdef JOBDEBUG
  272.     xprintf("errno == %d\n", errno);
  273. #endif
  274.     if (errno == EINTR) {
  275.         errno = 0;
  276.         goto loop;
  277.     }
  278.     pnoprocesses = pid == -1;
  279. #ifndef SIGVOID
  280.     return (0);
  281. #else /* !SIGVOID */
  282.     return;
  283. #endif /* SIGVOID */
  284.     }
  285.     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
  286.     if (pid == pp->p_procid)
  287.         goto found;
  288. #ifndef BSDJOBS
  289.     /* this should never have happened */
  290.     stderror(ERR_SYNC, pid);
  291.     xexit(0);
  292. #else /* BSDJOBS */
  293.     goto loop;
  294. #endif /* BSDJOBS */
  295. found:
  296.     if (pid == atoi(short2str(value(STRchild))))
  297.     unsetv(STRchild);
  298.     pp->p_flags &= ~(PRUNNING | PSTOPPED | PREPORTED);
  299.     if (WIFSTOPPED(w)) {
  300.     pp->p_flags |= PSTOPPED;
  301.     pp->p_reason = WSTOPSIG(w);
  302.     }
  303.     else {
  304.     if (pp->p_flags & (PTIME | PPTIME) || adrof(STRtime))
  305. #ifndef BSDTIMES
  306. # ifdef _SEQUENT_
  307.         (void) get_process_stats(&pp->p_etime, PS_SELF, NULL, NULL);
  308. # else    /* !_SEQUENT_ */
  309. #  ifndef COHERENT
  310.         pp->p_etime = times(&proctimes);
  311. #  else /* !COHERENT */
  312.         pp->p_etime = HZ * time(NULL);
  313.         times(&proctimes);
  314. #  endif /* !COHERENT */
  315. # endif    /* !_SEQUENT_ */
  316. #else /* BSDTIMES */
  317.         (void) gettimeofday(&pp->p_etime, NULL);
  318. #endif /* BSDTIMES */
  319.  
  320.  
  321. #if defined(BSDTIMES) || defined(_SEQUENT_)
  322.     pp->p_rusage = ru;
  323. #else /* !BSDTIMES && !_SEQUENT_ */
  324.     (void) times(&proctimes);
  325.     pp->p_utime = proctimes.tms_cutime - shtimes.tms_cutime;
  326.     pp->p_stime = proctimes.tms_cstime - shtimes.tms_cstime;
  327.     shtimes = proctimes;
  328. #endif /* !BSDTIMES && !_SEQUENT_ */
  329.     if (WIFSIGNALED(w)) {
  330.         if (WTERMSIG(w) == SIGINT)
  331.         pp->p_flags |= PINTERRUPTED;
  332.         else
  333.         pp->p_flags |= PSIGNALED;
  334.         if (WCOREDUMP(w))
  335.         pp->p_flags |= PDUMPED;
  336.         pp->p_reason = WTERMSIG(w);
  337.     }
  338.     else {
  339.         pp->p_reason = WEXITSTATUS(w);
  340.         if (pp->p_reason != 0)
  341.         pp->p_flags |= PAEXITED;
  342.         else
  343.         pp->p_flags |= PNEXITED;
  344.     }
  345.     }
  346.     jobflags = 0;
  347.     fp = pp;
  348.     do {
  349.     if ((fp->p_flags & (PPTIME | PRUNNING | PSTOPPED)) == 0 &&
  350.         !child && adrof(STRtime) &&
  351. #ifdef BSDTIMES
  352.         fp->p_rusage.ru_utime.tv_sec + fp->p_rusage.ru_stime.tv_sec
  353. #else /* !BSDTIMES */
  354. # ifdef _SEQUENT_
  355.         fp->p_rusage.ps_utime.tv_sec + fp->p_rusage.ps_stime.tv_sec
  356. # else /* !_SEQUENT_ */
  357. #  ifndef POSIX
  358.         (fp->p_utime + fp->p_stime) / HZ
  359. #  else /* POSIX */
  360.         (fp->p_utime + fp->p_stime) / clk_tck
  361. #  endif /* POSIX */
  362. # endif /* !_SEQUENT_ */
  363. #endif /* !BSDTIMES */
  364.         >= atoi(short2str(value(STRtime))))
  365.         fp->p_flags |= PTIME;
  366.     jobflags |= fp->p_flags;
  367.     } while ((fp = fp->p_friends) != pp);
  368.     pp->p_flags &= ~PFOREGND;
  369.     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  370.     pp->p_flags &= ~PPTIME;
  371.     pp->p_flags |= PTIME;
  372.     }
  373.     if ((jobflags & (PRUNNING | PREPORTED)) == 0) {
  374.     fp = pp;
  375.     do {
  376.         if (fp->p_flags & PSTOPPED)
  377.         fp->p_flags |= PREPORTED;
  378.     } while ((fp = fp->p_friends) != pp);
  379.     while (fp->p_procid != fp->p_jobid)
  380.         fp = fp->p_friends;
  381.     if (jobflags & PSTOPPED) {
  382.         if (pcurrent && pcurrent != fp)
  383.         pprevious = pcurrent;
  384.         pcurrent = fp;
  385.     }
  386.     else
  387.         pclrcurr(fp);
  388.     if (jobflags & PFOREGND) {
  389.         if (!(jobflags & (PSIGNALED | PSTOPPED | PPTIME) ||
  390. #ifdef IIASA
  391.         jobflags & PAEXITED ||
  392. #endif /* IIASA */
  393.         !eq(dcwd->di_name, fp->p_cwd->di_name))) {
  394.         /* PWP: print a newline after ^C */
  395.         if (jobflags & PINTERRUPTED) {
  396. #ifdef SHORT_STRINGS
  397.             xputchar('\r' | QUOTE), xputchar('\n');
  398. #else /* !SHORT_STRINGS */
  399.             xprintf("\215\n");    /* \215 is a quoted ^M */
  400. #endif /* !SHORT_STRINGS */
  401.         }
  402. #ifdef notdef
  403.         else if ((jobflags & (PTIME|PSTOPPED)) == PTIME)
  404.             ptprint(fp);
  405. #endif
  406.         }
  407.     }
  408.     else {
  409.         if (jobflags & PNOTIFY || adrof(STRnotify)) {
  410. #ifdef SHORT_STRINGS
  411.         xputchar('\r' | QUOTE), xputchar('\n');
  412. #else /* !SHORT_STRINGS */
  413.         xprintf("\215\n");    /* \215 is a quoted ^M */
  414. #endif /* !SHORT_STRINGS */
  415.         (void) pprint(pp, NUMBER | NAME | REASON);
  416.         if ((jobflags & PSTOPPED) == 0)
  417.             pflush(pp);
  418.         {
  419.             extern Char GettingInput;
  420.  
  421.             if (GettingInput) {
  422.             errno = 0;
  423.             (void) Rawmode();
  424. #ifdef notdef
  425.             /*
  426.              * don't really want to do that, because it
  427.              * will erase our message in case of multi-line
  428.              * input
  429.              */
  430.             ClearLines();
  431. #endif
  432.             ClearDisp();
  433.             Refresh();
  434.             }
  435.         }
  436.         }
  437.         else {
  438.         fp->p_flags |= PNEEDNOTE;
  439.         neednote++;
  440.         }
  441.     }
  442.     }
  443. #if defined(BSDJOBS) || defined(HAVEwait3)
  444.     goto loop;
  445. #endif /* BSDJOBS || HAVEwait3 */
  446. }
  447.  
  448. void
  449. pnote()
  450. {
  451.     register struct process *pp;
  452.     int     flags;
  453. #ifdef BSDSIGS
  454.     sigmask_t omask;
  455. #endif /* BSDSIGS */
  456.  
  457.     neednote = 0;
  458.     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next) {
  459.     if (pp->p_flags & PNEEDNOTE) {
  460. #ifdef BSDSIGS
  461.         omask = sigblock(sigmask(SIGCHLD));
  462. #else /* !BSDSIGS */
  463.         (void) sighold(SIGCHLD);
  464. #endif /* !BSDSIGS */
  465.         pp->p_flags &= ~PNEEDNOTE;
  466.         flags = pprint(pp, NUMBER | NAME | REASON);
  467.         if ((flags & (PRUNNING | PSTOPPED)) == 0)
  468.         pflush(pp);
  469. #ifdef BSDSIGS
  470.         (void) sigsetmask(omask);
  471. #else /* !BSDSIGS */
  472.         (void) sigrelse(SIGCHLD);
  473. #endif /* !BSDSIGS */
  474.     }
  475.     }
  476. }
  477.  
  478. /*
  479.  * pwait - wait for current job to terminate, maintaining integrity
  480.  *    of current and previous job indicators.
  481.  */
  482. void
  483. pwait()
  484. {
  485.     register struct process *fp, *pp;
  486. #ifdef BSDSIGS
  487.     sigmask_t omask;
  488. #endif /* BSDSIGS */
  489.  
  490.     /*
  491.      * Here's where dead procs get flushed.
  492.      */
  493. #ifdef BSDSIGS
  494.     omask = sigblock(sigmask(SIGCHLD));
  495. #else /* !BSDSIGS */
  496.     (void) sighold(SIGCHLD);
  497. #endif /* !BSDSIGS */
  498.     for (pp = (fp = &proclist)->p_next; pp != NULL; pp = (fp = pp)->p_next)
  499.     if (pp->p_procid == 0) {
  500.         fp->p_next = pp->p_next;
  501.         xfree((ptr_t) pp->p_command);
  502.         if (pp->p_cwd && --pp->p_cwd->di_count == 0)
  503.         if (pp->p_cwd->di_next == 0)
  504.             dfree(pp->p_cwd);
  505.         xfree((ptr_t) pp);
  506.         pp = fp;
  507.     }
  508. #ifdef BSDSIGS
  509.     (void) sigsetmask(omask);
  510. #else /* !BSDSIGS */
  511.     (void) sigrelse(SIGCHLD);
  512. # ifdef notdef
  513.     if (setintr)
  514.     sigignore(SIGINT);
  515. # endif
  516. #endif /* !BSDSIGS */
  517.     pjwait(pcurrjob);
  518. }
  519.  
  520.  
  521. /*
  522.  * pjwait - wait for a job to finish or become stopped
  523.  *    It is assumed to be in the foreground state (PFOREGND)
  524.  */
  525. void
  526. pjwait(pp)
  527.     register struct process *pp;
  528. {
  529.     register struct process *fp;
  530.     int     jobflags, reason;
  531. #ifdef BSDSIGS
  532.     sigmask_t omask;
  533. #endif /* BSDSIGS */
  534. #ifdef UNRELSIGS
  535.     sigret_t (*inthandler)();
  536. #endif /* UNRELSIGS */
  537.     while (pp->p_procid != pp->p_jobid)
  538.     pp = pp->p_friends;
  539.     fp = pp;
  540.  
  541.     do {
  542.     if ((fp->p_flags & (PFOREGND | PRUNNING)) == PRUNNING)
  543.         xprintf("BUG: waiting for background job!\n");
  544.     } while ((fp = fp->p_friends) != pp);
  545.     /*
  546.      * Now keep pausing as long as we are not interrupted (SIGINT), and the
  547.      * target process, or any of its friends, are running
  548.      */
  549.     fp = pp;
  550. #ifdef BSDSIGS
  551.     omask = sigblock(sigmask(SIGCHLD));
  552. #endif /* BSDSIGS */
  553. #ifdef UNRELSIGS
  554.     if (setintr)
  555.         inthandler = signal(SIGINT, SIG_IGN);
  556. #endif /* UNRELSIGS */
  557.     for (;;) {
  558. #ifndef BSDSIGS
  559.     (void) sighold(SIGCHLD);
  560. #endif /* !BSDSIGS */
  561.     jobflags = 0;
  562.     do
  563.         jobflags |= fp->p_flags;
  564.     while ((fp = (fp->p_friends)) != pp);
  565.     if ((jobflags & PRUNNING) == 0)
  566.         break;
  567. #ifdef JOBDEBUG
  568.     xprintf("starting to sigpause for  SIGCHLD on %d\n", fp->p_procid);
  569. #endif /* JOBDEBUG */
  570. #ifdef BSDSIGS
  571.     /* sigpause(sigblock((sigmask_t) 0) &~ sigmask(SIGCHLD)); */
  572.     (void) sigpause(omask & ~sigmask(SIGCHLD));
  573. #else /* !BSDSIGS */
  574.     (void) sigpause(SIGCHLD);
  575. #endif /* !BSDSIGS */
  576.     }
  577. #ifdef BSDSIGS
  578.     (void) sigsetmask(omask);
  579. #else /* !BSDSIGS */
  580.     (void) sigrelse(SIGCHLD);
  581. #endif /* !BSDSIGS */
  582. #ifdef UNRELSIGS
  583.     if (setintr)
  584.         (void) signal(SIGINT, inthandler);
  585. #endif /* UNRELSIGS */
  586. #ifdef BSDJOBS
  587.     if (tpgrp > 0)        /* get tty back */
  588.     (void) tcsetpgrp(FSHTTY, tpgrp);
  589. #endif /* BSDJOBS */
  590.     if ((jobflags & (PSIGNALED | PSTOPPED | PTIME)) ||
  591.     !eq(dcwd->di_name, fp->p_cwd->di_name)) {
  592.     if (jobflags & PSTOPPED) {
  593.         xputchar('\n');
  594.         if (adrof(STRlistjobs)) {
  595.         Char   *jobcommand[3];
  596.  
  597.         jobcommand[0] = STRjobs;
  598.         if (eq(value(STRlistjobs), STRlong))
  599.             jobcommand[1] = STRml;
  600.         else
  601.             jobcommand[1] = NULL;
  602.         jobcommand[2] = NULL;
  603.  
  604.         dojobs(jobcommand, NULL);
  605.         (void) pprint(pp, SHELLDIR);
  606.         }
  607.         else
  608.         (void) pprint(pp, AREASON | SHELLDIR);
  609.     }
  610.     else
  611.         (void) pprint(pp, AREASON | SHELLDIR);
  612.     }
  613.     if ((jobflags & (PINTERRUPTED | PSTOPPED)) && setintr &&
  614.     (!gointr || !eq(gointr, STRminus))) {
  615.     if ((jobflags & PSTOPPED) == 0)
  616.         pflush(pp);
  617.     pintr1(0);
  618.     /* NOTREACHED */
  619.     }
  620.     reason = 0;
  621.     fp = pp;
  622.     do {
  623.     if (fp->p_reason)
  624.         reason = fp->p_flags & (PSIGNALED | PINTERRUPTED) ?
  625.         fp->p_reason | META : fp->p_reason;
  626.     } while ((fp = fp->p_friends) != pp);
  627.     /*
  628.      * Don't report on backquoted jobs, cause it will mess up 
  629.      * their output.
  630.      */
  631.     if ((reason != 0) && (adrof(STRprintexitvalue)) && 
  632.     (pp->p_flags & PBACKQ) == 0)
  633.     xprintf("Exit %d\n", reason);
  634.     set(STRstatus, putn(reason));
  635.     if (reason && exiterr)
  636.     exitstat();
  637.     pflush(pp);
  638. }
  639.  
  640. /*
  641.  * dowait - wait for all processes to finish
  642.  */
  643.  
  644. /*ARGSUSED*/
  645. void
  646. dowait(v, c)
  647.     Char **v;
  648.     struct command *c;
  649. {
  650.     register struct process *pp;
  651. #ifdef BSDSIGS
  652.     sigmask_t omask;
  653. #endif /* BSDSIGS */
  654.  
  655.     pjobs++;
  656. #ifdef BSDSIGS
  657.     omask = sigblock(sigmask(SIGCHLD));
  658. loop:
  659. #else /* !BSDSIGS */
  660.     if (setintr)
  661.     (void) sigrelse(SIGINT);
  662. loop:
  663.     (void) sighold(SIGCHLD);
  664. #endif /* !BSDSIGS */
  665.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  666.     if (pp->p_procid &&    /* pp->p_procid == pp->p_jobid && */
  667.         pp->p_flags & PRUNNING) {
  668. #ifdef BSDSIGS
  669.         (void) sigpause((sigmask_t) 0);
  670. #else /* !BSDSIGS */
  671.         (void) sigpause(SIGCHLD);
  672. #endif /* !BSDSIGS */
  673.         goto loop;
  674.     }
  675. #ifdef BSDSIGS
  676.     (void) sigsetmask(omask);
  677. #else /* !BSDSIGS */
  678.     (void) sigrelse(SIGCHLD);
  679. #endif /* !BSDSIGS */
  680.     pjobs = 0;
  681. }
  682.  
  683. /*
  684.  * pflushall - flush all jobs from list (e.g. at fork())
  685.  */
  686. static void
  687. pflushall()
  688. {
  689.     register struct process *pp;
  690.  
  691.     for (pp = proclist.p_next; pp != NULL; pp = pp->p_next)
  692.     if (pp->p_procid)
  693.         pflush(pp);
  694. }
  695.  
  696. /*
  697.  * pflush - flag all process structures in the same job as the
  698.  *    the argument process for deletion.  The actual free of the
  699.  *    space is not done here since pflush is called at interrupt level.
  700.  */
  701. static void
  702. pflush(pp)
  703.     register struct process *pp;
  704. {
  705.     register struct process *np;
  706.     register int idx;
  707.  
  708.     if (pp->p_procid == 0) {
  709.     xprintf("BUG: process flushed twice");
  710.     return;
  711.     }
  712.     while (pp->p_procid != pp->p_jobid)
  713.     pp = pp->p_friends;
  714.     pclrcurr(pp);
  715.     if (pp == pcurrjob)
  716.     pcurrjob = 0;
  717.     idx = pp->p_index;
  718.     np = pp;
  719.     do {
  720.     np->p_index = np->p_procid = 0;
  721.     np->p_flags &= ~PNEEDNOTE;
  722.     } while ((np = np->p_friends) != pp);
  723.     if (idx == pmaxindex) {
  724.     for (np = proclist.p_next, idx = 0; np; np = np->p_next)
  725.         if (np->p_index > idx)
  726.         idx = np->p_index;
  727.     pmaxindex = idx;
  728.     }
  729. }
  730.  
  731. /*
  732.  * pclrcurr - make sure the given job is not the current or previous job;
  733.  *    pp MUST be the job leader
  734.  */
  735. static void
  736. pclrcurr(pp)
  737.     register struct process *pp;
  738. {
  739.     if (pp == pcurrent)
  740.     if (pprevious != NULL) {
  741.         pcurrent = pprevious;
  742.         pprevious = pgetcurr(pp);
  743.     }
  744.     else {
  745.         pcurrent = pgetcurr(pp);
  746.         pprevious = pgetcurr(pp);
  747.     }
  748.     else if (pp == pprevious)
  749.     pprevious = pgetcurr(pp);
  750. }
  751.  
  752. /* +4 here is 1 for '\0', 1 ea for << >& >> */
  753. static Char command[PMAXLEN + 4];
  754. static int cmdlen;
  755. static Char *cmdp;
  756.  
  757. /*
  758.  * palloc - allocate a process structure and fill it up.
  759.  *    an important assumption is made that the process is running.
  760.  */
  761. void
  762. palloc(pid, t)
  763.     int     pid;
  764.     register struct command *t;
  765. {
  766.     register struct process *pp;
  767.     int     i;
  768.  
  769.     pp = (struct process *) xcalloc(1, (size_t) sizeof(struct process));
  770.     pp->p_procid = pid;
  771.     pp->p_flags = ((t->t_dflg & F_AMPERSAND) ? 0 : PFOREGND) | PRUNNING;
  772.     if (t->t_dflg & F_TIME)
  773.     pp->p_flags |= PPTIME;
  774.     if (t->t_dflg & F_BACKQ)
  775.     pp->p_flags |= PBACKQ;
  776.     cmdp = command;
  777.     cmdlen = 0;
  778.     padd(t);
  779.     *cmdp++ = 0;
  780.     if (t->t_dflg & F_PIPEOUT) {
  781.     pp->p_flags |= PPOU;
  782.     if (t->t_dflg & F_STDERR)
  783.         pp->p_flags |= PDIAG;
  784.     }
  785.     pp->p_command = Strsave(command);
  786.     if (pcurrjob) {
  787.     struct process *fp;
  788.  
  789.     /* careful here with interrupt level */
  790.     pp->p_cwd = 0;
  791.     pp->p_index = pcurrjob->p_index;
  792.     pp->p_friends = pcurrjob;
  793.     pp->p_jobid = pcurrjob->p_procid;
  794.     for (fp = pcurrjob; fp->p_friends != pcurrjob; fp = fp->p_friends)
  795.         continue;
  796.     fp->p_friends = pp;
  797.     }
  798.     else {
  799.     pcurrjob = pp;
  800.     pp->p_jobid = pid;
  801.     pp->p_friends = pp;
  802.     pp->p_cwd = dcwd;
  803.     dcwd->di_count++;
  804.     if (pmaxindex < BIGINDEX)
  805.         pp->p_index = ++pmaxindex;
  806.     else {
  807.         struct process *np;
  808.  
  809.         for (i = 1;; i++) {
  810.         for (np = proclist.p_next; np; np = np->p_next)
  811.             if (np->p_index == i)
  812.             goto tryagain;
  813.         pp->p_index = i;
  814.         if (i > pmaxindex)
  815.             pmaxindex = i;
  816.         break;
  817.     tryagain:;
  818.         }
  819.     }
  820.     if (pcurrent == NULL)
  821.         pcurrent = pp;
  822.     else if (pprevious == NULL)
  823.         pprevious = pp;
  824.     }
  825.     pp->p_next = proclist.p_next;
  826.     proclist.p_next = pp;
  827. #ifdef BSDTIMES
  828.     (void) gettimeofday(&pp->p_btime, NULL);
  829. #else /* !BSDTIMES */
  830. # ifdef _SEQUENT_
  831.     (void) get_process_stats(&pp->p_btime, PS_SELF, NULL, NULL);
  832. # else /* !_SEQUENT_ */
  833.     {
  834.     struct tms tmptimes;
  835.  
  836. #  ifndef COHERENT
  837.     pp->p_btime = times(&tmptimes);
  838. #  else /* !COHERENT */
  839.     pp->p_btime = HZ * time(NULL);
  840.     times(&tmptimes);
  841. #  endif /* !COHERENT */
  842.     }
  843. # endif /* !_SEQUENT_ */
  844. #endif /* !BSDTIMES */
  845. }
  846.  
  847. static void
  848. padd(t)
  849.     register struct command *t;
  850. {
  851.     Char  **argp;
  852.  
  853.     if (t == 0)
  854.     return;
  855.     switch (t->t_dtyp) {
  856.  
  857.     case NODE_PAREN:
  858.     pads(STRLparensp);
  859.     padd(t->t_dspr);
  860.     pads(STRspRparen);
  861.     break;
  862.  
  863.     case NODE_COMMAND:
  864.     for (argp = t->t_dcom; *argp; argp++) {
  865.         pads(*argp);
  866.         if (argp[1])
  867.         pads(STRspace);
  868.     }
  869.     break;
  870.  
  871.     case NODE_OR:
  872.     case NODE_AND:
  873.     case NODE_PIPE:
  874.     case NODE_LIST:
  875.     padd(t->t_dcar);
  876.     switch (t->t_dtyp) {
  877.     case NODE_OR:
  878.         pads(STRspor2sp);
  879.         break;
  880.     case NODE_AND:
  881.         pads(STRspand2sp);
  882.         break;
  883.     case NODE_PIPE:
  884.         pads(STRsporsp);
  885.         break;
  886.     case NODE_LIST:
  887.         pads(STRsemisp);
  888.         break;
  889.     default:
  890.         break;
  891.     }
  892.     padd(t->t_dcdr);
  893.     return;
  894.  
  895.     default:
  896.     break;
  897.     }
  898.     if ((t->t_dflg & F_PIPEIN) == 0 && t->t_dlef) {
  899.     pads((t->t_dflg & F_READ) ? STRspLarrow2sp : STRspLarrowsp);
  900.     pads(t->t_dlef);
  901.     }
  902.     if ((t->t_dflg & F_PIPEOUT) == 0 && t->t_drit) {
  903.     pads((t->t_dflg & F_APPEND) ? STRspRarrow2 : STRspRarrow);
  904.     if (t->t_dflg & F_STDERR)
  905.         pads(STRand);
  906.     pads(STRspace);
  907.     pads(t->t_drit);
  908.     }
  909. }
  910.  
  911. static void
  912. pads(cp)
  913.     Char   *cp;
  914. {
  915.     register int i;
  916.  
  917.     /*
  918.      * Avoid the Quoted Space alias hack! Reported by:
  919.      * sam@john-bigboote.ICS.UCI.EDU (Sam Horrocks)
  920.      */
  921.     if (cp[0] == STRQNULL[0])
  922.     cp++;
  923.  
  924.     i = Strlen(cp);
  925.  
  926.     if (cmdlen >= PMAXLEN)
  927.     return;
  928.     if (cmdlen + i >= PMAXLEN) {
  929.     (void) Strcpy(cmdp, STRsp3dots);
  930.     cmdlen = PMAXLEN;
  931.     cmdp += 4;
  932.     return;
  933.     }
  934.     (void) Strcpy(cmdp, cp);
  935.     cmdp += i;
  936.     cmdlen += i;
  937. }
  938.  
  939. /*
  940.  * psavejob - temporarily save the current job on a one level stack
  941.  *    so another job can be created.  Used for { } in exp6
  942.  *    and `` in globbing.
  943.  */
  944. void
  945. psavejob()
  946. {
  947.     pholdjob = pcurrjob;
  948.     pcurrjob = NULL;
  949. }
  950.  
  951. /*
  952.  * prestjob - opposite of psavejob.  This may be missed if we are interrupted
  953.  *    somewhere, but pendjob cleans up anyway.
  954.  */
  955. void
  956. prestjob()
  957. {
  958.     pcurrjob = pholdjob;
  959.     pholdjob = NULL;
  960. }
  961.  
  962. /*
  963.  * pendjob - indicate that a job (set of commands) has been completed
  964.  *    or is about to begin.
  965.  */
  966. void
  967. pendjob()
  968. {
  969.     register struct process *pp, *tp;
  970.  
  971.     if (pcurrjob && (pcurrjob->p_flags & (PFOREGND | PSTOPPED)) == 0) {
  972.     pp = pcurrjob;
  973.     while (pp->p_procid != pp->p_jobid)
  974.         pp = pp->p_friends;
  975.     xprintf("[%d]", pp->p_index);
  976.     tp = pp;
  977.     do {
  978.         xprintf(" %d", pp->p_procid);
  979.         pp = pp->p_friends;
  980.     } while (pp != tp);
  981.     xputchar('\n');
  982.     }
  983.     pholdjob = pcurrjob = 0;
  984. }
  985.  
  986. /*
  987.  * pprint - print a job
  988.  */
  989.  
  990. /*
  991.  * Hacks have been added for SVR4 to deal with pipe's being spawned in
  992.  * reverse order
  993.  *
  994.  * David Dawes (dawes@physics.su.oz.au) Oct 1991
  995.  */
  996.  
  997. static int
  998. pprint(pp, flag)
  999.     register struct process *pp;
  1000.     bool    flag;
  1001. {
  1002.     register status, reason;
  1003.     struct process *tp;
  1004.     extern char *linp, linbuf[];
  1005.     int     jobflags, pstatus, pcond;
  1006.     char   *format;
  1007.  
  1008. #ifdef BACKPIPE
  1009.     struct process *pipehead = NULL, *pipetail = NULL, *pmarker = NULL;
  1010.     int inpipe = 0;
  1011. #endif /* BACKPIPE */
  1012.  
  1013.     while (pp->p_procid != pp->p_jobid)
  1014.     pp = pp->p_friends;
  1015.     if (pp == pp->p_friends && (pp->p_flags & PPTIME)) {
  1016.     pp->p_flags &= ~PPTIME;
  1017.     pp->p_flags |= PTIME;
  1018.     }
  1019.     tp = pp;
  1020.     status = reason = -1;
  1021.     jobflags = 0;
  1022.     do {
  1023. #ifdef BACKPIPE
  1024.     /*
  1025.      * The pipeline is reversed, so locate the real head of the pipeline
  1026.      * if pp is at the tail of a pipe (and not already in a pipeline)
  1027.      */
  1028.     if ((pp->p_friends->p_flags & PPOU) && !inpipe && (flag & NAME)) {
  1029.         inpipe = 1;
  1030.         pipetail = pp;
  1031.         do 
  1032.         pp = pp->p_friends;
  1033.         while (pp->p_friends->p_flags & PPOU);
  1034.         pipehead = pp;
  1035.         pmarker = pp;
  1036.     /*
  1037.      * pmarker is used to hold the place of the proc being processed, so
  1038.      * we can search for the next one downstream later.
  1039.      */
  1040.     }
  1041.     pcond = (tp != pp || (inpipe && tp == pp));
  1042. #else /* !BACKPIPE */
  1043.     pcond = (tp != pp);
  1044. #endif /* BACKPIPE */        
  1045.  
  1046.     jobflags |= pp->p_flags;
  1047.     pstatus = pp->p_flags & PALLSTATES;
  1048.     if (pcond && linp != linbuf && !(flag & FANCY) &&
  1049.         ((pstatus == status && pp->p_reason == reason) ||
  1050.          !(flag & REASON)))
  1051.         xputchar(' ');
  1052.     else {
  1053.         if (pcond && linp != linbuf)
  1054.         xputchar('\n');
  1055.         if (flag & NUMBER) {
  1056. #ifdef BACKPIPE
  1057.         pcond = ((pp == tp && !inpipe) ||
  1058.              (inpipe && pipetail == tp && pp == pipehead));
  1059. #else /* BACKPIPE */
  1060.         pcond = (pp == tp);
  1061. #endif /* BACKPIPE */
  1062.         if (pcond)
  1063.             xprintf("[%d]%s %c ", pp->p_index,
  1064.                 pp->p_index < 10 ? " " : "",
  1065.                 pp == pcurrent ? '+' :
  1066.                 (pp == pprevious ? '-' : ' '));
  1067.         else
  1068.             xprintf("       ");
  1069.         }
  1070.         if (flag & FANCY) {
  1071. #ifdef TCF
  1072.         extern char *sitename();
  1073.  
  1074. #endif /* TCF */
  1075.         xprintf("%5d ", pp->p_procid);
  1076. #ifdef TCF
  1077.         xprintf("%11s ", sitename(pp->p_procid));
  1078. #endif /* TCF */
  1079.         }
  1080.         if (flag & (REASON | AREASON)) {
  1081.         if (flag & NAME)
  1082. #ifdef SUSPENDED
  1083.             format = "%-23s";
  1084. #else /* !SUSPENDED */
  1085.             format = "%-21s";
  1086. #endif /* !SUSPENDED */
  1087.         else
  1088.             format = "%s";
  1089.         if (pstatus == status)
  1090.             if (pp->p_reason == reason) {
  1091.             xprintf(format, "");
  1092.             goto prcomd;
  1093.             }
  1094.             else
  1095.             reason = pp->p_reason;
  1096.         else {
  1097.             status = pstatus;
  1098.             reason = pp->p_reason;
  1099.         }
  1100.         switch (status) {
  1101.  
  1102.         case PRUNNING:
  1103.             xprintf(format, "Running ");
  1104.             break;
  1105.  
  1106.         case PINTERRUPTED:
  1107.         case PSTOPPED:
  1108.         case PSIGNALED:
  1109.             /*
  1110.              * tell what happened to the background job
  1111.              * From: Michael Schroeder 
  1112.              * <mlschroe@immd4.informatik.uni-erlangen.de>
  1113.              */
  1114.             if ((flag & REASON)
  1115.             || ((flag & AREASON)
  1116.                 && reason != SIGINT
  1117.                 && (reason != SIGPIPE
  1118.                 || (pp->p_flags & PPOU) == 0)))
  1119.             xprintf(format, mesg[pp->p_reason & ASCII].pname);
  1120.             else
  1121.             reason = -1;
  1122.             break;
  1123.  
  1124.         case PNEXITED:
  1125.         case PAEXITED:
  1126.             if (flag & REASON)
  1127.             if (pp->p_reason)
  1128. #ifdef SUSPENDED
  1129.                 xprintf("Exit %-18d", pp->p_reason);
  1130. #else /* SUSPENDED */
  1131.                 xprintf("Exit %-16d", pp->p_reason);
  1132. #endif /* SUSPENDED */
  1133.             else
  1134.                 xprintf(format, "Done");
  1135.             break;
  1136.  
  1137.         default:
  1138.             xprintf("BUG: status=%-9o", status);
  1139.         }
  1140.         }
  1141.     }
  1142. prcomd:
  1143.     if (flag & NAME) {
  1144.         xprintf("%S", pp->p_command);
  1145.         if (pp->p_flags & PPOU)
  1146.         xprintf(" |");
  1147.         if (pp->p_flags & PDIAG)
  1148.         xprintf("&");
  1149.     }
  1150.     if (flag & (REASON | AREASON) && pp->p_flags & PDUMPED)
  1151.         xprintf(" (core dumped)");
  1152.     if (tp == pp->p_friends) {
  1153.         if (flag & AMPERSAND)
  1154.         xprintf(" &");
  1155.         if (flag & JOBDIR &&
  1156.         !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1157.         xprintf(" (wd: ");
  1158.         dtildepr(value(STRhome), tp->p_cwd->di_name);
  1159.         xprintf(")");
  1160.         }
  1161.     }
  1162.     if (pp->p_flags & PPTIME && !(status & (PSTOPPED | PRUNNING))) {
  1163.         if (linp != linbuf)
  1164.         xprintf("\n\t");
  1165. #if defined(BSDTIMES) || defined(_SEQUENT_)
  1166.         prusage(&zru, &pp->p_rusage, &pp->p_etime,
  1167.             &pp->p_btime);
  1168. #else /* !BSDTIMES && !SEQUENT */
  1169.         lru.tms_utime = pp->p_utime;
  1170.         lru.tms_stime = pp->p_stime;
  1171.         lru.tms_cutime = 0;
  1172.         lru.tms_cstime = 0;
  1173.         prusage(&zru, &lru, pp->p_etime,
  1174.             pp->p_btime);
  1175. #endif /* !BSDTIMES && !SEQUENT */
  1176.  
  1177.     }
  1178. #ifdef BACKPIPE
  1179.     pcond = ((tp == pp->p_friends && !inpipe) ||
  1180.          (inpipe && pipehead->p_friends == tp && pp == pipetail));
  1181. #else  /* !BACKPIPE */
  1182.     pcond = (tp == pp->p_friends);
  1183. #endif /* BACKPIPE */
  1184.     if (pcond) {
  1185.         if (linp != linbuf)
  1186.         xputchar('\n');
  1187.         if (flag & SHELLDIR && !eq(tp->p_cwd->di_name, dcwd->di_name)) {
  1188.         xprintf("(wd now: ");
  1189.         dtildepr(value(STRhome), dcwd->di_name);
  1190.         xprintf(")\n");
  1191.         }
  1192.     }
  1193. #ifdef BACKPIPE
  1194.     if (inpipe) {
  1195.         /*
  1196.          * if pmaker == pipetail, we are finished that pipeline, and
  1197.          * can now skip to past the head
  1198.          */
  1199.         if (pmarker == pipetail) {
  1200.         inpipe = 0;
  1201.         pp = pipehead;
  1202.         }
  1203.         else {
  1204.         /*
  1205.          * set pp to one before the one we want next, so the while below
  1206.          * increments to the correct spot.
  1207.          */
  1208.         do
  1209.             pp = pp->p_friends;
  1210.             while (pp->p_friends->p_friends != pmarker);
  1211.             pmarker = pp->p_friends;
  1212.         }
  1213.     }
  1214.     pcond = ((pp = pp->p_friends) != tp || inpipe);
  1215. #else /* !BACKPIPE */
  1216.     pcond = ((pp = pp->p_friends) != tp);
  1217. #endif /* BACKPIPE */
  1218.     } while (pcond);
  1219.  
  1220.     if (jobflags & PTIME && (jobflags & (PSTOPPED | PRUNNING)) == 0) {
  1221.     if (jobflags & NUMBER)
  1222.         xprintf("       ");
  1223.     ptprint(tp);
  1224.     }
  1225.     return (jobflags);
  1226. }
  1227.  
  1228. /*
  1229.  * All 4.3 BSD derived implementations are buggy and I've had enough.
  1230.  * The following implementation produces similar code and works in all
  1231.  * cases. The 4.3BSD one works only for <, >, !=
  1232.  */
  1233. # undef timercmp
  1234. #  define timercmp(tvp, uvp, cmp) \
  1235.       (((tvp)->tv_sec == (uvp)->tv_sec) ? \
  1236.        ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
  1237.        ((tvp)->tv_sec  cmp (uvp)->tv_sec))
  1238.  
  1239. static void
  1240. ptprint(tp)
  1241.     register struct process *tp;
  1242. {
  1243. #ifdef BSDTIMES
  1244.     struct timeval tetime, diff;
  1245.     static struct timeval ztime;
  1246.     struct rusage ru;
  1247.     static struct rusage zru;
  1248.     register struct process *pp = tp;
  1249.  
  1250.     ru = zru;
  1251.     tetime = ztime;
  1252.     do {
  1253.     ruadd(&ru, &pp->p_rusage);
  1254.     tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1255.     if (timercmp(&diff, &tetime, >))
  1256.         tetime = diff;
  1257.     } while ((pp = pp->p_friends) != tp);
  1258.     prusage(&zru, &ru, &tetime, &ztime);
  1259. #else /* !BSDTIMES */
  1260. # ifdef _SEQUENT_
  1261.     timeval_t tetime, diff;
  1262.     static timeval_t ztime;
  1263.     struct process_stats ru;
  1264.     static struct process_stats zru;
  1265.     register struct process *pp = tp;
  1266.  
  1267.     ru = zru;
  1268.     tetime = ztime;
  1269.     do {
  1270.     ruadd(&ru, &pp->p_rusage);
  1271.     tvsub(&diff, &pp->p_etime, &pp->p_btime);
  1272.     if (timercmp(&diff, &tetime, >))
  1273.         tetime = diff;
  1274.     } while ((pp = pp->p_friends) != tp);
  1275.     prusage(&zru, &ru, &tetime, &ztime);
  1276. # else /* !_SEQUENT_ */
  1277. #  ifndef POSIX
  1278.     static time_t ztime = 0;
  1279.     static time_t zu_time = 0;
  1280.     static time_t zs_time = 0;
  1281.     time_t  tetime, diff;
  1282.     time_t  u_time, s_time;
  1283.  
  1284. #  else    /* POSIX */
  1285.     static clock_t ztime = 0;
  1286.     static clock_t zu_time = 0;
  1287.     static clock_t zs_time = 0;
  1288.     clock_t tetime, diff;
  1289.     clock_t u_time, s_time;
  1290.  
  1291. #  endif /* POSIX */
  1292.     struct tms zts, rts;
  1293.     register struct process *pp = tp;
  1294.  
  1295.     u_time = zu_time;
  1296.     s_time = zs_time;
  1297.     tetime = ztime;
  1298.     do {
  1299.     u_time += pp->p_utime;
  1300.     s_time += pp->p_stime;
  1301.     diff = pp->p_etime - pp->p_btime;
  1302.     if (diff > tetime)
  1303.         tetime = diff;
  1304.     } while ((pp = pp->p_friends) != tp);
  1305.     zts.tms_utime = zu_time;
  1306.     zts.tms_stime = zs_time;
  1307.     zts.tms_cutime = 0;
  1308.     zts.tms_cstime = 0;
  1309.     rts.tms_utime = u_time;
  1310.     rts.tms_stime = s_time;
  1311.     rts.tms_cutime = 0;
  1312.     rts.tms_cstime = 0;
  1313.     prusage(&zts, &rts, tetime, ztime);
  1314. # endif /* !_SEQUENT_ */
  1315. #endif    /* !BSDTIMES */
  1316. }
  1317.  
  1318. /*
  1319.  * dojobs - print all jobs
  1320.  */
  1321. /*ARGSUSED*/
  1322. void
  1323. dojobs(v, c)
  1324.     Char  **v;
  1325.     struct command *c;
  1326. {
  1327.     register struct process *pp;
  1328.     register int flag = NUMBER | NAME | REASON;
  1329.     int     i;
  1330.  
  1331.     if (chkstop)
  1332.     chkstop = 2;
  1333.     if (*++v) {
  1334.     if (v[1] || !eq(*v, STRml))
  1335.         stderror(ERR_JOBS);
  1336.     flag |= FANCY | JOBDIR;
  1337.     }
  1338.     for (i = 1; i <= pmaxindex; i++)
  1339.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1340.         if (pp->p_index == i && pp->p_procid == pp->p_jobid) {
  1341.         pp->p_flags &= ~PNEEDNOTE;
  1342.         if (!(pprint(pp, flag) & (PRUNNING | PSTOPPED)))
  1343.             pflush(pp);
  1344.         break;
  1345.         }
  1346. }
  1347.  
  1348. /*
  1349.  * dofg - builtin - put the job into the foreground
  1350.  */
  1351. /*ARGSUSED*/
  1352. void
  1353. dofg(v, c)
  1354.     Char  **v;
  1355.     struct command *c;
  1356. {
  1357.     register struct process *pp;
  1358.  
  1359.     okpcntl();
  1360.     ++v;
  1361.     do {
  1362.     pp = pfind(*v);
  1363.     pstart(pp, 1);
  1364. #ifndef BSDSIGS
  1365. # ifdef notdef
  1366.     if (setintr)
  1367.         sigignore(SIGINT);
  1368. # endif
  1369. #endif /* !BSDSIGS */
  1370.     pjwait(pp);
  1371.     } while (*v && *++v);
  1372. }
  1373.  
  1374. /*
  1375.  * %... - builtin - put the job into the foreground
  1376.  */
  1377. /*ARGSUSED*/
  1378. void
  1379. dofg1(v, c)
  1380.     Char  **v;
  1381.     struct command *c;
  1382. {
  1383.     register struct process *pp;
  1384.  
  1385.     okpcntl();
  1386.     pp = pfind(v[0]);
  1387.     pstart(pp, 1);
  1388. #ifndef BSDSIGS
  1389. # ifdef notdef
  1390.     if (setintr)
  1391.     sigignore(SIGINT);
  1392. # endif
  1393. #endif /* !BSDSIGS */
  1394.     pjwait(pp);
  1395. }
  1396.  
  1397. /*
  1398.  * dobg - builtin - put the job into the background
  1399.  */
  1400. /*ARGSUSED*/
  1401. void
  1402. dobg(v, c)
  1403.     Char  **v;
  1404.     struct command *c;
  1405. {
  1406.     register struct process *pp;
  1407.  
  1408.     okpcntl();
  1409.     ++v;
  1410.     do {
  1411.     pp = pfind(*v);
  1412.     pstart(pp, 0);
  1413.     } while (*v && *++v);
  1414. }
  1415.  
  1416. /*
  1417.  * %... & - builtin - put the job into the background
  1418.  */
  1419. /*ARGSUSED*/
  1420. void
  1421. dobg1(v, c)
  1422.     Char  **v;
  1423.     struct command *c;
  1424. {
  1425.     register struct process *pp;
  1426.  
  1427.     pp = pfind(v[0]);
  1428.     pstart(pp, 0);
  1429. }
  1430.  
  1431. /*
  1432.  * dostop - builtin - stop the job
  1433.  */
  1434. /*ARGSUSED*/
  1435. void
  1436. dostop(v, c)
  1437.     Char  **v;
  1438.     struct command *c;
  1439. {
  1440. #ifdef BSDJOBS
  1441.     pkill(++v, SIGSTOP);
  1442. #endif /* BSDJOBS */
  1443. }
  1444.  
  1445. /*
  1446.  * dokill - builtin - superset of kill (1)
  1447.  */
  1448. /*ARGSUSED*/
  1449. void
  1450. dokill(v, c)
  1451.     Char  **v;
  1452.     struct command *c;
  1453. {
  1454.     register int signum, len = 0;
  1455.     register char *name;
  1456.     extern int T_Cols;
  1457.  
  1458.     v++;
  1459.     if (v[0] && v[0][0] == '-') {
  1460.     if (v[0][1] == 'l') {
  1461.         for (signum = 1; signum <= NSIG; signum++) {
  1462.         if ((name = mesg[signum].iname) != NULL) {
  1463.             len += strlen(name) + 1;
  1464.             if (len >= T_Cols - 1) {
  1465.             xputchar('\n');
  1466.             len = strlen(name) + 1;
  1467.             }
  1468.             xprintf("%s ", name);
  1469.         }
  1470.         }
  1471.         xputchar('\n');
  1472.         return;
  1473.     }
  1474.     if (Isdigit(v[0][1])) {
  1475.         signum = atoi(short2str(v[0] + 1));
  1476.         if (signum < 0 || signum > NSIG)
  1477.         stderror(ERR_NAME | ERR_BADSIG);
  1478.     }
  1479.     else {
  1480.         for (signum = 1; signum <= NSIG; signum++)
  1481.         if (mesg[signum].iname &&
  1482.             eq(&v[0][1], str2short(mesg[signum].iname)))
  1483.             goto gotsig;
  1484.         setname(short2str(&v[0][1]));
  1485.         stderror(ERR_NAME | ERR_UNKSIG);
  1486.     }
  1487. gotsig:
  1488.     v++;
  1489.     }
  1490.     else
  1491.     signum = SIGTERM;
  1492.     pkill(v, signum);
  1493. }
  1494.  
  1495. static void
  1496. pkill(v, signum)
  1497.     Char  **v;
  1498.     int     signum;
  1499. {
  1500.     register struct process *pp, *np;
  1501.     int jobflags = 0, err1 = 0;
  1502.     pid_t     pid;
  1503. #ifdef BSDSIGS
  1504.     sigmask_t omask;
  1505. #endif /* BSDSIGS */
  1506.     Char   *cp;
  1507.  
  1508. #ifdef BSDSIGS
  1509.     omask = sigmask(SIGCHLD);
  1510.     if (setintr)
  1511.     omask |= sigmask(SIGINT);
  1512.     omask = sigblock(omask) & ~omask;
  1513. #else /* !BSDSIGS */
  1514.     if (setintr)
  1515.     (void) sighold(SIGINT);
  1516.     (void) sighold(SIGCHLD);
  1517. #endif /* !BSDSIGS */
  1518.     gflag = 0, tglob(v);
  1519.     if (gflag) {
  1520.     v = globall(v);
  1521.     if (v == 0)
  1522.         stderror(ERR_NAME | ERR_NOMATCH);
  1523.     }
  1524.     else {
  1525.     v = gargv = saveblk(v);
  1526.     trim(v);
  1527.     }
  1528.  
  1529.     while (v && (cp = *v)) {
  1530.     if (*cp == '%') {
  1531.         np = pp = pfind(cp);
  1532.         do
  1533.         jobflags |= np->p_flags;
  1534.         while ((np = np->p_friends) != pp);
  1535. #ifdef BSDJOBS
  1536.         switch (signum) {
  1537.  
  1538.         case SIGSTOP:
  1539.         case SIGTSTP:
  1540.         case SIGTTIN:
  1541.         case SIGTTOU:
  1542.         if ((jobflags & PRUNNING) == 0) {
  1543. # ifdef SUSPENDED
  1544.             xprintf("%S: Already suspended\n", cp);
  1545. # else /* !SUSPENDED */
  1546.             xprintf("%S: Already stopped\n", cp);
  1547. # endif /* !SUSPENDED */
  1548.             err1++;
  1549.             goto cont;
  1550.         }
  1551.         break;
  1552.         /*
  1553.          * suspend a process, kill -CONT %, then type jobs; the shell
  1554.          * says it is suspended, but it is running; thanks jaap..
  1555.          */
  1556.         case SIGCONT:
  1557.         pstart(pp, 0);
  1558.         goto cont;
  1559.         default:
  1560.         break;
  1561.         }
  1562. #endif /* BSDJOBS */
  1563.         if (killpg(pp->p_jobid, signum) < 0) {
  1564.         xprintf("%S: %s\n", cp, strerror(errno));
  1565.         err1++;
  1566.         }
  1567. #ifdef BSDJOBS
  1568.         if (signum == SIGTERM || signum == SIGHUP)
  1569.         (void) killpg(pp->p_jobid, SIGCONT);
  1570. #endif /* BSDJOBS */
  1571.     }
  1572.     else if (!(Isdigit(*cp) || *cp == '-'))
  1573.         stderror(ERR_NAME | ERR_JOBARGS);
  1574.     else {
  1575.         pid = atoi(short2str(cp));
  1576.         if (kill(pid, signum) < 0) {
  1577.         xprintf("%d: %s\n", pid, strerror(errno));
  1578.         err1++;
  1579.         goto cont;
  1580.         }
  1581. #ifdef BSDJOBS
  1582.         if (signum == SIGTERM || signum == SIGHUP)
  1583.         (void) kill(pid, SIGCONT);
  1584. #endif /* BSDJOBS */
  1585.     }
  1586. cont:
  1587.     v++;
  1588.     }
  1589.     if (gargv)
  1590.     blkfree(gargv), gargv = 0;
  1591. #ifdef BSDSIGS
  1592.     (void) sigsetmask(omask);
  1593. #else /* !BSDSIGS */
  1594.     (void) sigrelse(SIGCHLD);
  1595.     if (setintr)
  1596.     (void) sigrelse(SIGINT);
  1597. #endif /* !BSDSIGS */
  1598.     if (err1)
  1599.     stderror(ERR_SILENT);
  1600. }
  1601.  
  1602. /*
  1603.  * pstart - start the job in foreground/background
  1604.  */
  1605. void
  1606. pstart(pp, foregnd)
  1607.     register struct process *pp;
  1608.     int     foregnd;
  1609. {
  1610.     register struct process *np;
  1611. #ifdef BSDSIGS
  1612.     sigmask_t omask;
  1613. #endif /* BSDSIGS */
  1614.     long    jobflags = 0;
  1615.  
  1616. #ifdef BSDSIGS
  1617.     omask = sigblock(sigmask(SIGCHLD));
  1618. #else /* !BSDSIGS */
  1619.     (void) sighold(SIGCHLD);
  1620. #endif
  1621.     np = pp;
  1622.     do {
  1623.     jobflags |= np->p_flags;
  1624.     if (np->p_flags & (PRUNNING | PSTOPPED)) {
  1625.         np->p_flags |= PRUNNING;
  1626.         np->p_flags &= ~PSTOPPED;
  1627.         if (foregnd)
  1628.         np->p_flags |= PFOREGND;
  1629.         else
  1630.         np->p_flags &= ~PFOREGND;
  1631.     }
  1632.     } while ((np = np->p_friends) != pp);
  1633.     if (!foregnd)
  1634.     pclrcurr(pp);
  1635.     (void) pprint(pp, foregnd ? NAME | JOBDIR : NUMBER | NAME | AMPERSAND);
  1636. #ifdef BSDJOBS
  1637.     if (foregnd) {
  1638.     (void) tcsetpgrp(FSHTTY, pp->p_jobid);
  1639.     }
  1640.     /*
  1641.      * 1. child process of csh (shell script) receives SIGTTIN/SIGTTOU
  1642.      * 2. parent process (csh) receives SIGCHLD
  1643.      * 3. The "csh" signal handling function pchild() is invoked
  1644.      *    with a SIGCHLD signal.
  1645.      * 4. pchild() calls wait3(WNOHANG) which returns 0.
  1646.      *    The child process is NOT ready to be waited for at this time.
  1647.      *    pchild() returns without picking-up the correct status
  1648.      *    for the child process which generated the SIGCHILD.
  1649.      * 5. CONSEQUENCE : csh is UNaware that the process is stopped
  1650.      * 6. THIS LINE HAS BEEN COMMENTED OUT : if (jobflags&PSTOPPED)
  1651.      *       (beto@aixwiz.austin.ibm.com - aug/03/91)
  1652.      */
  1653.  
  1654.     /* if (jobflags & PSTOPPED) */
  1655.     (void) killpg(pp->p_jobid, SIGCONT);
  1656. #endif /* BSDJOBS */
  1657. #ifdef BSDSIGS
  1658.     (void) sigsetmask(omask);
  1659. #else /* !BSDSIGS */
  1660.     (void) sigrelse(SIGCHLD);
  1661. #endif /* !BSDSIGS */
  1662. }
  1663.  
  1664. void
  1665. panystop(neednl)
  1666.     bool    neednl;
  1667. {
  1668.     register struct process *pp;
  1669.  
  1670.     chkstop = 2;
  1671.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1672.     if (pp->p_flags & PSTOPPED)
  1673.         stderror(ERR_STOPPED, neednl ? "\n" : "");
  1674. }
  1675.  
  1676. struct process *
  1677. pfind(cp)
  1678.     Char   *cp;
  1679. {
  1680.     register struct process *pp, *np;
  1681.  
  1682.     if (cp == 0 || cp[1] == 0 || eq(cp, STRcent2) || eq(cp, STRcentplus)) {
  1683.     if (pcurrent == NULL)
  1684.         stderror(ERR_NAME | ERR_JOBCUR);
  1685.     return (pcurrent);
  1686.     }
  1687.     if (eq(cp, STRcentminus) || eq(cp, STRcenthash)) {
  1688.     if (pprevious == NULL)
  1689.         stderror(ERR_NAME | ERR_JOBPREV);
  1690.     return (pprevious);
  1691.     }
  1692.     if (Isdigit(cp[1])) {
  1693.     int     idx = atoi(short2str(cp + 1));
  1694.  
  1695.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1696.         if (pp->p_index == idx && pp->p_procid == pp->p_jobid)
  1697.         return (pp);
  1698.     stderror(ERR_NAME | ERR_NOSUCHJOB);
  1699.     }
  1700.     np = NULL;
  1701.     for (pp = proclist.p_next; pp; pp = pp->p_next)
  1702.     if (pp->p_procid == pp->p_jobid) {
  1703.         if (cp[1] == '?') {
  1704.         register Char *dp;
  1705.  
  1706.         for (dp = pp->p_command; *dp; dp++) {
  1707.             if (*dp != cp[2])
  1708.             continue;
  1709.             if (prefix(cp + 2, dp))
  1710.             goto match;
  1711.         }
  1712.         }
  1713.         else if (prefix(cp + 1, pp->p_command)) {
  1714.     match:
  1715.         if (np)
  1716.             stderror(ERR_NAME | ERR_AMBIG);
  1717.         np = pp;
  1718.         }
  1719.     }
  1720.     if (np)
  1721.     return (np);
  1722.     stderror(ERR_NAME | (cp[1] == '?' ? ERR_JOBPAT : ERR_NOSUCHJOB));
  1723.     /* NOTREACHED */
  1724.     return (0);
  1725. }
  1726.  
  1727.  
  1728. /*
  1729.  * pgetcurr - find most recent job that is not pp, preferably stopped
  1730.  */
  1731. static struct process *
  1732. pgetcurr(pp)
  1733.     register struct process *pp;
  1734. {
  1735.     register struct process *np;
  1736.     register struct process *xp = NULL;
  1737.  
  1738.     for (np = proclist.p_next; np; np = np->p_next)
  1739.     if (np != pcurrent && np != pp && np->p_procid &&
  1740.         np->p_procid == np->p_jobid) {
  1741.         if (np->p_flags & PSTOPPED)
  1742.         return (np);
  1743.         if (xp == NULL)
  1744.         xp = np;
  1745.     }
  1746.     return (xp);
  1747. }
  1748.  
  1749. /*
  1750.  * donotify - flag the job so as to report termination asynchronously
  1751.  */
  1752. /*ARGSUSED*/
  1753. void
  1754. donotify(v, c)
  1755.     Char  **v;
  1756.     struct command *c;
  1757. {
  1758.     register struct process *pp;
  1759.  
  1760.     pp = pfind(*++v);
  1761.     pp->p_flags |= PNOTIFY;
  1762. }
  1763.  
  1764. /*
  1765.  * Do the fork and whatever should be done in the child side that
  1766.  * should not be done if we are not forking at all (like for simple builtin's)
  1767.  * Also do everything that needs any signals fiddled with in the parent side
  1768.  *
  1769.  * Wanttty tells whether process and/or tty pgrps are to be manipulated:
  1770.  *    -1:    leave tty alone; inherit pgrp from parent
  1771.  *     0:    already have tty; manipulate process pgrps only
  1772.  *     1:    want to claim tty; manipulate process and tty pgrps
  1773.  * It is usually just the value of tpgrp.
  1774.  */
  1775.  
  1776. int
  1777. pfork(t, wanttty)
  1778.     struct command *t;        /* command we are forking for */
  1779.     int     wanttty;
  1780. {
  1781.     register int pid;
  1782.     bool    ignint = 0;
  1783.     int     pgrp;
  1784. #ifdef BSDSIGS
  1785.     sigmask_t omask;
  1786. #endif /* BSDSIGS */
  1787. #ifdef SIGSYNCH
  1788.     sigvec_t osv;
  1789.     static sigvec_t nsv = {synch_handler, ~0, 0};
  1790. #endif /* SIGSYNCH */
  1791.  
  1792.     /*
  1793.      * A child will be uninterruptible only under very special conditions.
  1794.      * Remember that the semantics of '&' is implemented by disconnecting the
  1795.      * process from the tty so signals do not need to ignored just for '&'.
  1796.      * Thus signals are set to default action for children unless: we have had
  1797.      * an "onintr -" (then specifically ignored) we are not playing with
  1798.      * signals (inherit action)
  1799.      */
  1800.     if (setintr)
  1801.     ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT))
  1802.         || (gointr && eq(gointr, STRminus));
  1803.  
  1804. #ifdef COHERENT
  1805.     ignint |= gointr && eq(gointr, STRminus);
  1806. #endif /* COHERENT */
  1807.  
  1808.     /*
  1809.      * Check for maximum nesting of 16 processes to avoid Forking loops
  1810.      */
  1811.     if (child == 16)
  1812.     stderror(ERR_NESTING, 16);
  1813.     /*
  1814.      * Hold SIGCHLD until we have the process installed in our table.
  1815.      */
  1816. #ifdef SIGSYNCH
  1817.     if (mysigvec(SIGSYNCH, &nsv, &osv))
  1818.     stderror(ERR_SYSTEM, "pfork: sigvec set", strerror(errno));
  1819. #endif /* SIGSYNCH */
  1820. #ifdef BSDSIGS
  1821.     omask = sigblock(sigmask(SIGCHLD));
  1822. #else /* !BSDSIGS */
  1823.     (void) sighold(SIGCHLD);
  1824. #endif /* !BSDSIGS */
  1825.     while ((pid = fork()) < 0)
  1826.     if (setintr == 0)
  1827.         (void) sleep(FORKSLEEP);
  1828.     else {
  1829. #ifdef BSDSIGS
  1830.         (void) sigsetmask(omask);
  1831. #else /* !BSDSIGS */
  1832.         (void) sigrelse(SIGINT);
  1833.         (void) sigrelse(SIGCHLD);
  1834. #endif /* !BSDSIGS */
  1835.         stderror(ERR_NOPROC);
  1836.     }
  1837.     if (pid == 0) {
  1838.     settimes();
  1839.     pgrp = pcurrjob ? pcurrjob->p_jobid : getpid();
  1840.     pflushall();
  1841.     pcurrjob = NULL;
  1842. #if !defined(BSDTIMES) && !defined(_SEQUENT_) 
  1843.     timesdone = 0;
  1844. #endif /* !defined(BSDTIMES) && !defined(_SEQUENT_) */
  1845.     child++;
  1846.     if (setintr) {
  1847.         setintr = 0;    /* until I think otherwise */
  1848. #ifndef BSDSIGS
  1849.         (void) sigrelse(SIGCHLD);
  1850. #endif /* !BSDSIGS */
  1851.         /*
  1852.          * Children just get blown away on SIGINT, SIGQUIT unless "onintr
  1853.          * -" seen.
  1854.          */
  1855.         (void) signal(SIGINT, ignint ? SIG_IGN : SIG_DFL);
  1856.         (void) signal(SIGQUIT, ignint ? SIG_IGN : SIG_DFL);
  1857. #ifdef BSDJOBS
  1858.         if (wanttty >= 0) {
  1859.         /* make stoppable */
  1860.         (void) signal(SIGTSTP, SIG_DFL);
  1861.         (void) signal(SIGTTIN, SIG_DFL);
  1862.         (void) signal(SIGTTOU, SIG_DFL);
  1863.         }
  1864. #endif /* BSDJOBS */
  1865.         (void) signal(SIGTERM, parterm);
  1866.     }
  1867.     else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) {
  1868.         (void) signal(SIGINT, SIG_IGN);
  1869.         (void) signal(SIGQUIT, SIG_IGN);
  1870.     }
  1871. #ifdef OREO
  1872.     sigignore(SIGIO);    /* ignore SIGIO in child too */
  1873. #endif /* OREO */
  1874.  
  1875.     pgetty(wanttty, pgrp);
  1876.     /*
  1877.      * Nohup and nice apply only to NODE_COMMAND's but it would be nice
  1878.      * (?!?) if you could say "nohup (foo;bar)" Then the parser would have
  1879.      * to know about nice/nohup/time
  1880.      */
  1881.     if (t->t_dflg & F_NOHUP)
  1882.         (void) signal(SIGHUP, SIG_IGN);
  1883.     if (t->t_dflg & F_NICE)
  1884. #ifdef BSDNICE
  1885.         (void) setpriority(PRIO_PROCESS, 0, t->t_nice);
  1886. #else /* !BSDNICE */
  1887.         (void) nice(t->t_nice);
  1888. #endif /* !BSDNICE */
  1889. #ifdef F_VER
  1890.         if (t->t_dflg & F_VER) {
  1891.         tsetenv(STRSYSTYPE, t->t_systype ? STRbsd43 : STRsys53);
  1892.         dohash(NULL, NULL);
  1893.     }
  1894. #endif /* F_VER */
  1895. #ifdef SIGSYNCH
  1896.     /* rfw 8/89 now parent can continue */
  1897.     if (kill(getppid(), SIGSYNCH))
  1898.         stderror(ERR_SYSTEM, "pfork child: kill", strerror(errno));
  1899. #endif /* SIGSYNCH */
  1900.  
  1901.     }
  1902.     else {
  1903. #ifdef POSIXJOBS
  1904.         if (wanttty >= 0) {
  1905.         /*
  1906.          * `Walking' process group fix from Beto Appleton.
  1907.          * (beto@aixwiz.austin.ibm.com)
  1908.          * If setpgid fails at this point that means that
  1909.          * our process leader has died. We flush the current
  1910.          * job and become the process leader ourselves.
  1911.          * The parent will figure that out later.
  1912.          */
  1913.         pgrp = pcurrjob ? pcurrjob->p_jobid : pid;
  1914.         if (setpgid(pid, pgrp) == -1 && errno == EPERM) {
  1915.         pflush(pcurrjob);
  1916.         pcurrjob = NULL;
  1917.         if (setpgid(pid, pgrp = pid) == -1) {
  1918.             stderror(ERR_SYSTEM, "setpgid parent:", strerror(errno));
  1919.             xexit(0);
  1920.         }
  1921.         }
  1922.     }
  1923. #endif /* POSIXJOBS */
  1924.     palloc(pid, t);
  1925. #ifdef SIGSYNCH
  1926.     /*
  1927.      * rfw 8/89 Wait for child to own terminal.  Solves half of ugly
  1928.      * synchronization problem.  With this change, we know that the only
  1929.      * reason setpgrp to a previous process in a pipeline can fail is that
  1930.      * the previous process has already exited. Without this hack, he may
  1931.      * either have exited or not yet started to run.  Two uglies become
  1932.      * one.
  1933.      */
  1934.     sigpause(omask & ~SYNCHMASK);
  1935.     if (mysigvec(SIGSYNCH, &osv, NULL))
  1936.         stderror(ERR_SYSTEM, "pfork parent: sigvec restore",
  1937.              strerror(errno));
  1938. #endif /* SIGSYNCH */
  1939.  
  1940. #ifdef BSDSIGS
  1941.     (void) sigsetmask(omask);
  1942. #else /* !BSDSIGS */
  1943.     (void) sigrelse(SIGCHLD);
  1944. #endif /* !BSDSIGS */
  1945.     }
  1946.     return (pid);
  1947. }
  1948.  
  1949. static void
  1950. okpcntl()
  1951. {
  1952.     if (tpgrp == -1)
  1953.     stderror(ERR_JOBCONTROL);
  1954.     if (tpgrp == 0)
  1955.     stderror(ERR_JOBCTRLSUB);
  1956. }
  1957.  
  1958. /*
  1959.  * if we don't have vfork(), things can still go in the wrong order
  1960.  * resulting in the famous 'Stopped (tty output)'. But some systems
  1961.  * don't permit the setpgid() call, (these are more recent secure
  1962.  * systems such as ibm's aix), when they do. Then we'd rather print 
  1963.  * an error message than hang the shell!
  1964.  * I am open to suggestions how to fix that.
  1965.  */
  1966. void
  1967. pgetty(wanttty, pgrp)
  1968.     int     wanttty, pgrp;
  1969. {
  1970. #ifdef BSDJOBS
  1971. # if defined(BSDSIGS) && defined(POSIXJOBS)
  1972.     sigmask_t omask = 0;
  1973. # endif /* BSDSIGS && POSIXJOBS */
  1974.  
  1975. # ifdef JOBDEBUG
  1976.     xprintf("wanttty %d\n", wanttty);
  1977. # endif
  1978.  
  1979. # ifdef POSIXJOBS
  1980.     /*
  1981.      * christos: I am blocking the tty signals till I've set things
  1982.      * correctly....
  1983.      */
  1984.     if (wanttty > 0)
  1985. #  ifdef BSDSIGS
  1986.     omask = sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN));
  1987. #  else /* !BSDSIGS */
  1988.     {
  1989.     (void) sighold(SIGTSTP);
  1990.     (void) sighold(SIGTTIN);
  1991.     }
  1992. #  endif /* !BSDSIGS */
  1993. # endif /* POSIXJOBS */
  1994.  
  1995. # ifndef POSIXJOBS
  1996.     if (wanttty > 0)
  1997.     (void) tcsetpgrp(FSHTTY, pgrp);
  1998. # endif /* !POSIXJOBS */
  1999.  
  2000.     /*
  2001.      * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de>
  2002.      * Don't check for tpgrp >= 0 so even non-interactive shells give
  2003.      * background jobs process groups Same for the comparison in the other part
  2004.      * of the #ifdef
  2005.      */
  2006.     if (wanttty >= 0)
  2007.     if (setpgid(0, pgrp) == -1) {
  2008. # ifdef POSIXJOBS
  2009.         /* Walking process group fix; see above */
  2010.         if (setpgid(0, pgrp = getpid()) == -1) {
  2011. # endif /* POSIXJOBS */
  2012.         stderror(ERR_SYSTEM, "setpgid child:\n", strerror(errno));
  2013.         xexit(0);
  2014. # ifdef POSIXJOBS
  2015.         }
  2016.         wanttty = 1;  /* Now we really want the tty, since we became the
  2017.                * the process group leader
  2018.                */
  2019. # endif /* POSIXJOBS */
  2020.     }
  2021.  
  2022. # ifdef POSIXJOBS
  2023. #  ifdef _SEQUENT_
  2024.     /* The controlling terminal is lost if all processes in the
  2025.      * terminal process group are zombies. In this case tcgetpgrp()
  2026.      * returns 0. If this happens we must set the terminal process
  2027.      * group again.
  2028.      */
  2029.     if (wanttty == 0 && tcgetpgrp(FSHTTY) == 0)
  2030.         wanttty = 1;
  2031. #  endif /* _SEQUENT_ */
  2032.     if (wanttty > 0) {
  2033.         /*
  2034.      * tcsetpgrp will set SIGTTOU to all the the processes in 
  2035.      * the background according to POSIX... We ignore this here.
  2036.      */
  2037.     sigret_t (*old)() = sigset(SIGTTOU, SIG_IGN);
  2038.     (void) tcsetpgrp(FSHTTY, pgrp);
  2039.     (void) sigset(SIGTTOU, old);
  2040.  
  2041. #  ifdef BSDSIGS
  2042.     (void) sigsetmask(omask);
  2043. #  else /* BSDSIGS */
  2044.     (void) sigrelse(SIGTSTP);
  2045.     (void) sigrelse(SIGTTIN);
  2046. #  endif /* !BSDSIGS */
  2047.     }
  2048. # endif /* POSIXJOBS */
  2049.  
  2050.     if (tpgrp > 0)
  2051.     tpgrp = 0;        /* gave tty away */
  2052. #endif /* BSDJOBS */
  2053. }
  2054.